"""
The create new component wizard.

Copyright (c) 2008 Rune M. Friborg, runef@diku.dk.
See LICENSE.txt for licensing details (GPLv2).
"""

from plugins.system import *

import sys
import os
import wx
import wx.wizard as wiz

class WizardPageChooseType(wiz.PyWizardPage):
    def __init__(self, parent, title, componentLib, pageA, page3):
        wiz.PyWizardPage.__init__(self, parent)
        self.next = self.prev = None
        self.nextPageA = pageA
        self.updatePage3 = page3
        
        # Title
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        title = wx.StaticText(self, -1, title)
        title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
        self.sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL)

        self.sizer.Add(wx.StaticText(self, -1, "Package:"), 0, wx.ALL, 5 ) 
        package_list =  componentLib.getPackageList().keys()
        package_list.sort()
        self.packageName = wx.ComboBox(
            self, 500, 'default', (100, 50),  
            (130, -1), package_list, wx.CB_DROPDOWN
            )
        self.sizer.Add(self.packageName, 0, wx.ALL, 5)        

        self.sizer.Add(wx.StaticText(self,-1, "Component:"), 0, wx.ALL, 0)
        self.componentName = wx.TextCtrl(self, -1, "Untitled", size=(125,-1))
        self.sizer.Add(self.componentName, 0, wx.ALL, 5)

        self.sizer.Add(wx.StaticText(self,-1, "Input channels:"), 0, wx.ALL, 0)
        self.inC = wx.SpinCtrl(self, -1, "", (30,50))
        self.inC.SetRange(0,1000000)
        self.inC.SetValue(0)
        self.sizer.Add(self.inC, 0, wx.ALL, 5)

        self.sizer.Add(wx.StaticText(self,-1, "Output channels:"), 0, wx.ALL, 0)
        self.outC = wx.SpinCtrl(self, -1, "", (30,50))
        self.outC.SetRange(0,1000000)
        self.outC.SetValue(0)
        self.sizer.Add(self.outC, 0, wx.ALL, 5)

        # Draw plugins
        #global_pluginman.draw(location_PROCESS, 1, dc, self, position, selected)

        self.conf = wx.CheckBox(self, -1, "configurable")
        self.sizer.Add(self.conf, 0, wx.ALL, 5)

    def SetNext(self, next):
        self.next = next

    def SetPrev(self, prev):
        self.prev = prev

    def GetNext(self):
        self.next = self.nextPageA
            
        self.next.UpdateForm(self.componentName.GetValue(), self.inC.GetValue(), self.outC.GetValue(), self.conf.GetValue())
        self.updatePage3.componentFilename.SetValue(self.componentName.GetValue())
        return self.next

    def GetPrev(self):
        return self.prev


class WizardPageAddComponent(wiz.PyWizardPage):
    def __init__(self, parent, title, pluginmanager):
        wiz.PyWizardPage.__init__(self, parent)
        self.next = self.prev = None

        # Title
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        title = wx.StaticText(self, -1, title)
        title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
        self.sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL)
        
        radioList = []
        for path in pluginmanager.getList(pathlist_COMPONENTS):
            radioList.append('Add to ' + path)
        
        self.rb = wx.RadioBox(
                self, -1, "", wx.DefaultPosition, wx.DefaultSize,
                radioList, 1, wx.RA_SPECIFY_COLS | wx.NO_BORDER
                )


        self.sizer.Add(self.rb, 0, wx.ALL, 5)

        self.sizer.Add(wx.StaticText(self,-1, "Filename of component .csp file:"), 0, wx.ALL, 0)
        self.componentFilename = wx.TextCtrl(self, -1, '', size=(125,-1))
        self.sizer.Add(self.componentFilename, 0, wx.ALL, 5)
        

    def SetNext(self, next):
        self.next = next

    def SetPrev(self, prev):
        self.prev = prev

    def GetNext(self):
        return self.next

    def GetPrev(self):
        return self.prev


class WizardPageSetupImpl1(wiz.PyWizardPage):
    def __init__(self, parent, title):
        wiz.PyWizardPage.__init__(self, parent)
        self.next = self.prev = None

        # Title
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        title = wx.StaticText(self, -1, title)
        title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
        self.sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 5)


        radioList = []
        self.templateList = []
        filename = 'WizardImplTemplate'
        i = 1
        while os.path.exists(sys.path[0] + '/' + 'Internal/WizardImplTemplate' + str(i) + '.py'):
           x = __import__(filename + str(i))
           radioList.append(x.__doc__)
           self.templateList.append(filename + str(i))
           i = i + 1

        self.sizer.Add(wx.StaticText(self,-1, "Choose template:"), 0, wx.ALL, 0)
        self.rb = wx.RadioBox(
                self, -1, "", wx.DefaultPosition, wx.DefaultSize,
                radioList, 1, wx.RA_SPECIFY_COLS | wx.NO_BORDER
                )

        self.sizer.Add(self.rb, 0, wx.ALL, 5)

        self.sizer.Add(wx.StaticText(self,-1, "Filename of new .py file:"), 0, wx.ALL, 0)
        self.pythonFilename = wx.TextCtrl(self, -1, '', size=(125,-1))
        self.sizer.Add(self.pythonFilename, 0, wx.ALL, 5)



    def UpdateForm(self, componentName, inC, outC, configurable):

        self.saved = [componentName, inC, outC, configurable]
        self.pythonFilename.SetValue(componentName)
           
           
    def SetNext(self, next):
        self.next = next

    def SetPrev(self, prev):
        self.prev = prev

    def GetNext(self):
        if (self.next != None):
           apply( self.next.UpdateForm, self.saved + [self.templateList[self.rb.GetSelection()]])
        return self.next
     
    def GetPrev(self):
        return self.prev

class WizardPageSetupImpl2(wiz.PyWizardPage):
    def __init__(self, parent, title):
        wiz.PyWizardPage.__init__(self, parent)
        self.next = self.prev = None

        # Title
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        title = wx.StaticText(self, -1, title)
        title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
        self.sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 5)
        
        self.code = wx.TextCtrl(self, -1,'',
                       size=(200, 100), style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER)
        self.sizer.Add(self.code, 1, wx.ALL|wx.GROW, 1)

        self.SetAutoLayout(True)

    def UpdateForm(self, processName, inC, outC, configurable, template):

        self.saved = [processName, inC, outC, configurable, template]

        # Create sample code.
        wizard_channels = ''
        wizard_inchannels = ''
        wizard_readchannels = [] 
        wizard_writechannels = []
        wizard_poisonreadchannels = []
        wizard_poisonwritechannels = []
        wizard_imports = ['']
        wizard_work = ["#Insert work here"]
           
        for i in range(inC):
           wizard_channels += ',' + 'in' + str(i)
           wizard_inchannels += ',' + 'in' + str(i)
           wizard_readchannels.append('val' + str(i) + ' = in' + str(i) + '()')
           wizard_poisonreadchannels.append('poison(in' + str(i) + ')')
        
        for i in range(outC):
           wizard_channels += ',' + 'out' + str(i)
           wizard_writechannels.append('out' + str(i) + '(result' + str(i) + ')')
           wizard_poisonwritechannels.append('poison(out' + str(i) + ')')
           
        wizard_channels = wizard_channels[1:]
        wizard_inchannels = wizard_inchannels[1:]

        f = open(sys.path[0] + '/Internal/' + template + '.py', 'r')
        pyCode = ""
        for line in f.readlines():

           if (line.find('#__IMPORTS__') == -1 and
               line.find('__WORK__') == -1 and
               line.find('___READCHANNELS___') == -1 and
               line.find('___WRITECHANNELS___') == -1 and
               line.find('___POISONREADCHANNELS___') == -1 and
               line.find('___POISONWRITECHANNELS___') == -1):
              pyCode = pyCode + line.replace('___FUNCTIONNAME___', processName+'Func').replace('___CHANNELS___', wizard_channels)
           else:
              pyCode = pyCode + self.replaceLineWithStringList(line, '#__IMPORTS__', wizard_imports)
              pyCode = pyCode + self.replaceLineWithStringList(line, '__WORK__', wizard_work)
              pyCode = pyCode + self.replaceLineWithStringList(line, '___READCHANNELS___', wizard_readchannels)
              pyCode = pyCode + self.replaceLineWithStringList(line, '___WRITECHANNELS___', wizard_writechannels)
              pyCode = pyCode + self.replaceLineWithStringList(line, '___POISONREADCHANNELS___', wizard_poisonreadchannels)
              pyCode = pyCode + self.replaceLineWithStringList(line, '___POISONWRITECHANNELS___', wizard_poisonwritechannels)
              

        #self.code = pyCode
        self.code.SetValue(pyCode)

    def replaceLineWithStringList(self, line, id, stringList):
       result = ''
       if (line.find(id) != -1):
          for x in stringList:
             result = result + line.replace(id, x)
       return result
       
    def SetNext(self, next):
        self.next = next

    def SetPrev(self, prev):
        self.prev = prev

    def GetNext(self):
        if (self.next != None and 'UpdateForm' in dir(self.next)):
           apply( self.next.UpdateForm, self.saved)
        return self.next

     
    def GetPrev(self):
        return self.prev


class WizardPageDone(wiz.PyWizardPage):
    def __init__(self, parent, title):
        wiz.PyWizardPage.__init__(self, parent)
        self.next = self.prev = None

        # Title
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        title = wx.StaticText(self, -1, title)
        title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
        self.sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 5)

        self.sizer.Add(wx.StaticText(self,-1, "Click finish to create component."), 0, wx.ALL, 10)

    def SetNext(self, next):
        self.next = next

    def SetPrev(self, prev):
        self.prev = prev

    def GetNext(self):
        return self.next
     
    def GetPrev(self):
        return self.prev



def runCreateProcessWizard(panel, pluginmanager, componentlib):

   # Create the wizard and the pages
   wizard = wiz.Wizard(panel, -1, "Create Component Wizard")

   page2aa = WizardPageSetupImpl1(wizard, "Python implementation step 1 (2/4)")
   page2ab = WizardPageSetupImpl2(wizard, "Python implementation step 2 (2/4)")
   page3 = WizardPageAddComponent(wizard, "Add component (3/4)", pluginmanager)
   page4 = WizardPageDone(wizard, "Final page (4/4)")

   page1 = WizardPageChooseType(wizard, "Add Component wizard (1/4)", componentlib, page2aa, page3)
      
   panel.page1 = page1

   wizard.FitToPage(page1)
   wizard.FitToPage(page2aa)
   wizard.FitToPage(page2ab)
   wizard.FitToPage(page3)
   wizard.FitToPage(page4)

   # Set the initial order of the pages
   page1.SetNext(page2aa)
   page2aa.SetPrev(page1)
   page2aa.SetNext(page2ab)
   page2ab.SetPrev(page2aa)
   page2ab.SetNext(page3)

   page3.SetPrev(page2ab)
   page3.SetNext(page4)
   page4.SetPrev(page3)

   wizard.GetPageAreaSizer().Add(page1)
   if wizard.RunWizard(page1):
       # Create component
       # Values
       # page1.packageName.GetValue() : string
       # page1.componentName.GetValue() : string
       # page1.inC.GetValue() : int 
       # page1.outC.GetValue() : int
       # page1.conf.GetValue() : True / False
       # page2aa.pythonFilename.GetValue() : string
       # page2ab.code : python code
       # page3.rb.GetSelection() : 0 or 1..
         
       data = {'packageName':page1.packageName.GetValue(),
               'componentName':page1.componentName.GetValue(),
               'inChannels':page1.inC.GetValue(),
               'outChannels':page1.outC.GetValue(),
               'configurable':page1.conf.GetValue()}

       # Python
       data['pythonFilename'] = page2aa.pythonFilename.GetValue()
       data['code'] = page2ab.code.GetValue()


       data['componentPath'] = pluginmanager.getList(pathlist_COMPONENTS)[page3.rb.GetSelection()]
      
       data['componentFilename'] = page3.componentFilename.GetValue()
         
       return data
   else:
       # return none
       return {}

   wizard.Destroy()

